#!/usr/bin/python
# @Time  : 2020/3/25 15:58
# @Author: LOUIE
# @Desc  : 工具函数
from utils.exceptions import ParamsError, VariableNotFound, NotFoundError
from utils import parser
from utils.logger import log
import jsonpath
import json
import config
from smtplib import SMTP


def print_request_log(name, method, url, kwargs):
    identifier = ' = ' * 6
    log.info(f"processed request: {name}")
    log.info(f"{identifier} request detail {identifier}")
    log.info(f"[ {method} ] {url}")

    kwarg_copy = kwargs.copy()
    if kwarg_copy.get('headers'):
        log.info(f"headers: {kwarg_copy.pop('headers')}")
    if kwarg_copy.get('files'):
        log.info(f"files: {kwarg_copy.pop('files')}")
    if not kwarg_copy:
        return

    key = "params"
    if kwarg_copy.get('json'):
        key = 'json'
    elif kwarg_copy.get('data'):
        key = 'data'
    elif kwarg_copy.get('params'):
        key = 'params'

    log.info(f'{key}: 'f"\n{json.dumps(kwarg_copy.pop(key), indent=4, ensure_ascii=False)}")

    if kwarg_copy:
        log.info(f'kwargs: {kwarg_copy}')


def get_target_value(obj, expr):
    """
    获取JSON数据中的指定key的value值
    :param obj: dict, 字典对象
    :param expr: str, 表达式或者取值的key，通过判断是否存在"$"符号进行取值
    :return:
    """
    if not isinstance(obj, dict):
        return "TypeError: unexpected types, only supported dict"

    if not isinstance(expr, str):
        return  "TypeError: unexpected types, only supported str"

    if '$' in expr:
        expr = expr
    else:
        expr = '$..{}'.format(str(expr))
    field_value = jsonpath.jsonpath(obj=obj, expr=expr)[0]

    return field_value


def format_variable(variables):
    if isinstance(variables, list):
        variables_dict = {}
        for map_dict in variables:
            variables_dict.update(map_dict)

        return variables_dict

    elif isinstance(variables, dict):
        return variables

    else:
        raise ParamsError("variables format error!")


def parse_variables_pool(variables_mapping):
    run_times = 0
    parsed_variables_mapping = {}

    while len(parsed_variables_mapping) != len(variables_mapping):
        for var_name in variables_mapping:

            run_times += 1
            if run_times > len(variables_mapping) * 4:
                not_found_variables = {
                    key: variables_mapping[key]
                    for key in variables_mapping
                    if key not in parsed_variables_mapping
                }
                raise VariableNotFound(not_found_variables)

            if var_name in parsed_variables_mapping:
                continue

            value = variables_mapping[var_name]
            variables = parser.extract_variables(value)

            if var_name in variables:
                raise VariableNotFound(var_name)

            if variables:

                if any([_var_name not in parsed_variables_mapping for _var_name in variables]):
                    continue

            parsed_value = parser.parse_data(value, parsed_variables_mapping)
            parsed_variables_mapping[var_name] = parsed_value

    return parsed_variables_mapping


def parse_summary(result):
    if not result:
        raise NotFoundError("Result not found !.")

    summary = {
        'start_time': result[0]['start_time'],
        'duration': result[0]['duration'],
        'passed': result[1]['p']['number'],
        'passed_percent': result[1]['p']['percent'],
        'failed': result[1]['f']['number'],
        'total': 0,
    }
    for detail in result[1:]:
        for k, v in detail.items():
            for q, w in v.items():
                if q == 'number':
                    summary['total'] = summary['total'] + w

    return summary


def send_email(report):
    try:
        smtp = SMTP(user=config.EMAIL_USERNAME, password=config.EMAIL_PASSWORD, host=config.EMAIL_HOST)
        smtp.sender(to=config.EMAIL_RECEIVER, subject=config.EMAIL_SUBJECT, attachments=report)
        log.info('Email sent successfully.')
    except:
        log.error('Email sending failure.')
